package com.mac.web;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 基础Servlet类，继承自HttpServlet。
 * 该类的主要功能是根据请求的最后一段路径来进行方法分发。
 */
public class BaseServlet extends HttpServlet {

    // 使用SLF4J记录日志
    private static final Logger LOGGER = LoggerFactory.getLogger("BaseServlet.Class");

    /**
     * 根据请求的最后一段路径来进行方法分发。
     * 重写service方法，以便在接收到请求时自动调用。
     * @param req 请求对象，包含请求信息。
     * @param resp 响应对象，用于返回响应数据。
     * @throws ServletException 如果发生Servlet异常。
     * @throws IOException 如果发生I/O异常。
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求路径
        String uri = req.getRequestURI();

        // 获取最后一段路径，即方法名
        int index = uri.lastIndexOf('/');
        String methodName = uri.substring(index + 1);

        // 执行对应的方法
        // 获取字节码对象，即Class对象
        Class<? extends BaseServlet> cls = this.getClass();

        try {
            // 获取方法对象，即Method对象
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            LOGGER.info("cls.getMethod -> succeed");
            // 执行方法
            method.invoke(this, req, resp);
            LOGGER.info("invoke(this,req,resp) -> succeed");
        } catch (NoSuchMethodException e) {
            // 没有找到对应的方法
            LOGGER.error("cls.getMethod -> failed", e);
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            // 无法访问对应的方法
            LOGGER.error("invoke(this,req,resp) -> failed", e);
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            // 方法执行时抛出异常
            LOGGER.error("invoke(this,req,resp) -> failed", e);
            throw new RuntimeException(e);
        }
    }
}